/* Elasticity.ado (STATA)
	Estimate demand elasticity.
	by Ralph Koijen & Motohiro Yogo */

#delimit ;

program Elasticity, rclass;
args n t coef;


/* Load data */

u "../3 Estimation/Estimation`n'", clear;

/* Change coefficient to compute gradient */

qui if !missing("`coef'") {; 
	replace `coef' = `coef'*(1+$step) if type==`t';
};

/* Demand shifters */

gen shifter = b_cons+eps;

qui foreach var of varlist $macro $bilateral $dummies {;
	replace shifter = shifter+b_`var'*`var';
};

/* Aggregate demand shifters */

gen shifterA = bA_cons+epsA;


/* Estimation by issuer country and asset type */

qui gen elast = .;

qui levelsof counter_euro if type==`t';

qui foreach i in `r(levels)' {;
	forval j = 0/1 {;

		/* Change price */

		gen Lmb`j' = Lmb;
		replace Lmb`j' = Lmb+(`j'-.5)*$step if counter_euro=="`i'" & type==`t';

		/* Expected returns in USD */

		gen EretCF = c_Lmb*Lmb`j'+c_Lrealfx*Lrealfx+c_cons;

		/* Adjust expected returns to local currency */

		egen Eret_LCU = total(EretCF*(type==1 & Iycounterpart)), missing by(year country);

		replace EretCF = EretCF-Eret_LCU;

		drop Eret_LCU;

		/* Construct inner portfolio weights */

		gen delta = exp(b_Eret*EretCF+shifter);

		egen Sdelta = total(delta), missing by(year country type);
		replace Sdelta = 1+Sdelta;

		gen weight = delta/Sdelta;

		drop EretCF delta;

		/* Construct outer portfolio weights */

		gen Sdelta1 = Sdelta^bA_LSrw1*exp(shifterA) if type==1;
		replace Sdelta1 = Sdelta^bA_LSrw2*exp(shifterA) if type==2;
		replace Sdelta1 = Sdelta^bA_LSrw3*exp(shifterA) if type==3;

		egen Sdelta2 = total(Sdelta1*Iycountry), missing by(year country);

		gen weightA = Sdelta1/Sdelta2;

		drop Sdelta*;

		/* Construct wealth */

		egen wealthCF = total(amount*exp(Lmb`j'-Lmb)), missing by(year country);
		replace wealthCF = wealthCF+outside;

		/* Construct demand */

		egen demand`j' = total(wealthCF*weight*weightA), missing by(year counter_euro type);

		drop weight* wealthCF;
	};

	/* Estimate elasticity */

	replace elast = 1-(ln(demand1)-ln(demand0))/(Lmb1-Lmb0) if counter_euro=="`i'" & type==`t';

	drop Lmb0 Lmb1 demand*;
};

/* Fix variables */

qui replace Name = "Euro" if counter_euro=="EUR";

/* Keep estimates only */

qui keep if type==`t' & Iycounter_euro;

keep year counter_euro Name type `coef' elast;

/* Return estimates */

qui if missing("`coef'") {;

	/* Label variables */

	label var elast "Elasticity";

	/* Save estimates */

	sort year counter_euro type;

	save Elasticity`n'_`t', replace;

	/* Estimate mean elasticity */

	sum elast;

	return scalar Melast = r(mean);
};
qui else {;

	/* Rename variables */

	rename elast Celast;

	/* Merge estimates */

	merge 1:1 year counter_euro using Elasticity`n'_`t',
		keepusing(elast)
		nogen;

	/* Compute gradient */

	gen Delast = (Celast-elast)/(`coef'*$step);

	/* Estimate mean gradient */

	sum Delast;

	return scalar Delast = r(mean);
};

end;
